home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 16 / AMIGAplus Sonderheft 16 (1998)(ICP)(DE)[!].iso / pd / anwendungen / xpk_source / shell / xpack.c < prev    next >
C/C++ Source or Header  |  1998-02-08  |  11KB  |  474 lines

  1. #include <xpk/xpkobsolete.h>
  2. #include <exec/alerts.h>
  3. #include <exec/memory.h>
  4. #include <exec/execbase.h>
  5.  
  6. #include <dos/dosextens.h>
  7. #include <dos/dosasl.h>
  8. #include <dos/rdargs.h>
  9.  
  10. #include <xpk/xpk.h>
  11. #include <proto/exec.h>
  12. #include <proto/dos.h>
  13. #include <proto/xpkmaster.h>
  14.  
  15. #include <string.h>
  16.  
  17. #define XFH_ID "XFH A"
  18.  
  19. void PrintF(char *,...);
  20. LONG __regargs PackFile(struct DosLibrary *DOSBase,struct Library *XpkBase,
  21.                         char *,struct FileInfoBlock *,char *,char *,LONG,char *,
  22.                         LONG,LONG,LONG,LONG,LONG);
  23. LONG __regargs UnPackFile(struct DosLibrary *DOSBase,struct Library *XpkBase,
  24.                           char *,char *,struct FileInfoBlock *,char *,LONG);
  25. LONG __asm __saveds ChunkFunc(register __a1 struct XpkProgress *);
  26.  
  27. struct Hook ChunkHook = {{0L},ChunkFunc};
  28.  
  29. struct xPackArgs
  30.  {
  31.   char **Files;
  32.   char *Method;
  33.   ULONG *MinSize;
  34.   char *Suffix,*Password;
  35.   LONG All,Force,Program,xScan,Lossy,Quiet;
  36.  };
  37.  
  38. char *VersionString = "$VER: xPack 1.5 ("__DATE__")";
  39. char *Template =
  40.  "FILE/M/A,METHOD/K,MINSIZE/N/K,SUFFIX/K,PASSWORD/K,"
  41.  "ALL/S,FORCE/S,PROGRAM/S,XSCAN/S,LOSSY/S,QUIET/S";
  42.  
  43. LONG __saveds main(void)
  44. {
  45.  struct DosLibrary *DOSBase;
  46.  struct Library *XpkBase;
  47.  struct Process *MyProc;
  48.  struct RDArgs *RDArgs;
  49.  char ProgName[32];
  50.  LONG Result;
  51.  struct xPackArgs Args;
  52.  char **Files;
  53.  struct AnchorPath *AnchorPath;
  54.  ULONG MinSize;
  55.  
  56.  if ((MyProc=(struct Process *)FindTask(NULL))->pr_CLI==NULL)
  57.   {
  58.    (void)WaitPort(&MyProc->pr_MsgPort);
  59.    Forbid();
  60.    ReplyMsg (GetMsg(&MyProc->pr_MsgPort));
  61.  
  62.    return 0L;
  63.   }
  64.  
  65.  if ((DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",33L))==NULL)
  66.   {
  67.    Alert (AT_Recovery|AG_OpenLib|AO_DOSLib);
  68.  
  69.    return 20L;
  70.   }
  71.  if (DOSBase->dl_lib.lib_Version<37L)
  72.   {
  73.    (void)Write(Output(),"This program requires OS 2.04 or newer.\n",40L);
  74.  
  75.    CloseLibrary (&DOSBase->dl_lib);
  76.    return 20L;
  77.   }
  78.  
  79.  if (!GetProgramName(ProgName,32L)) (void)strcpy(ProgName,"xPack");
  80.  Result=10L;
  81.  
  82.  if ((XpkBase=OpenLibrary(XPKNAME,2L))==NULL)
  83.   {
  84.    PrintF ("%s: %s V2 or newer required !\n",ProgName,XPKNAME);
  85.  
  86.    goto Close1;
  87.   }
  88.  
  89.  Args.Files=NULL;
  90.  Args.Method=Args.Suffix=Args.Password=NULL;
  91.  Args.MinSize=NULL;
  92.  Args.All=Args.Force=Args.Program=Args.xScan=Args.Lossy=Args.Quiet=FALSE;
  93.  if ((RDArgs=ReadArgs(Template,(LONG *)&Args,NULL))==NULL)
  94.   {
  95.    PrintFault (IoErr(),ProgName);
  96.  
  97.    goto Close2;
  98.   }
  99.  
  100.  if (Args.MinSize) MinSize=*Args.MinSize;
  101.  else MinSize=512L;
  102.  if (Args.Password) Args.Force=TRUE;
  103.  
  104.  if ((AnchorPath=(struct AnchorPath *)AllocVec(sizeof(struct AnchorPath)+256L,
  105.                                                MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  106.   {
  107.    PrintFault (ERROR_NO_FREE_STORE,ProgName);
  108.  
  109.    goto Close3;
  110.   }
  111.  AnchorPath->ap_BreakBits=SIGBREAKF_CTRL_C;
  112.  AnchorPath->ap_Strlen=256;
  113.  
  114.  Files=Args.Files;
  115.  while (*Files)
  116.   {
  117.    LONG RetVal;
  118.  
  119.    for (RetVal=MatchFirst(*Files,AnchorPath); RetVal==0L; RetVal=MatchNext(AnchorPath))
  120.     {
  121.      if (AnchorPath->ap_Info.fib_DirEntryType>0L)
  122.       {
  123.        if (((AnchorPath->ap_Flags&APF_DIDDIR)==0L)&&Args.All)
  124.         AnchorPath->ap_Flags|=APF_DODIR;
  125.        AnchorPath->ap_Flags&=~APF_DIDDIR;
  126.       }
  127.      else
  128.       {
  129.        BPTR DirLock;
  130.        LONG Result;
  131.  
  132.        DirLock=CurrentDir(AnchorPath->ap_Current->an_Lock);
  133.        if (Args.Method==NULL)
  134.         Result=UnPackFile(DOSBase,XpkBase,
  135.                           AnchorPath->ap_Buf,Args.Suffix,&AnchorPath->ap_Info,
  136.                           Args.Password,Args.Quiet);
  137.        else
  138.         Result=PackFile(DOSBase,XpkBase,
  139.                         AnchorPath->ap_Buf,&AnchorPath->ap_Info,Args.Method,
  140.                         Args.Suffix,MinSize,Args.Password,
  141.                         Args.Force,Args.Program,Args.xScan,Args.Lossy,Args.Quiet);
  142.        (void)CurrentDir(DirLock);
  143.  
  144.        if (!Result)
  145.         {
  146.          PrintF ("\n*** Aborting\n");
  147.  
  148.          MatchEnd (AnchorPath);
  149.          goto Close4;
  150.         }
  151.       }
  152.     }
  153.    MatchEnd (AnchorPath);
  154.  
  155.    if (RetVal!=ERROR_NO_MORE_ENTRIES)
  156.     {
  157.      PrintF ("%s: %s - ",ProgName,*Files);
  158.      PrintFault (RetVal,NULL);
  159.      
  160.      goto Close4;
  161.     }
  162.    else Files++;
  163.   }
  164.  Result=0L;
  165.  
  166. Close4: /* I hate "goto"s, but it's the only way to keep it short. */
  167.  FreeVec ((APTR)AnchorPath);
  168. Close3:
  169.  FreeArgs (RDArgs);
  170. Close2:
  171.  CloseLibrary (XpkBase);
  172. Close1:
  173.  CloseLibrary (&DOSBase->dl_lib);
  174.  return Result;
  175. }
  176.  
  177. void PrintF(char *FormatString,...)
  178.  
  179. {
  180.  struct DosLibrary *DOSBase;
  181.  
  182.  if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L))
  183.   {
  184.    (void)VPrintf(FormatString,(LONG *)&FormatString+1L);
  185.    (void)Flush(Output());
  186.  
  187.    CloseLibrary (&DOSBase->dl_lib);
  188.   }
  189. }
  190.  
  191. void __regargs TempName(char *Name)
  192.  
  193. {
  194.  UWORD Index;
  195.  ULONG Addr;
  196.  
  197.  for (Index=0, Addr=(ULONG)FindTask(NULL); Index<8; Index++, Addr>>=4)
  198.   *Name++='A'+(char)(Addr&15);
  199.  (void)strcpy(Name,".zop");
  200. }
  201.  
  202. LONG __asm __saveds ChunkFunc(register __a1 struct XpkProgress *Prog)
  203.  
  204. {
  205.  if (Prog->Type==XPKPROG_START ) PrintF ("\x1B[0 p");
  206.  PrintF ("\r%-9s %-12s (%6ld bytes, %3ld%% done, %2ld%% CF) ",
  207.          Prog->Activity,Prog->FileName,Prog->ULen,Prog->Done,Prog->CF);
  208.  if (Prog->Type==XPKPROG_END) PrintF ("\n\x1B[1 p");
  209.  
  210.  return (LONG)SetSignal(0L,SIGBREAKF_CTRL_C)&SIGBREAKF_CTRL_C;
  211. }
  212.  
  213. char *ULTA(char *Ptr,ULONG LW)
  214.  
  215. {
  216.  UWORD Index;
  217.  
  218.  *Ptr++=' ';
  219.  for (Index=0; Index<8; Index++, LW>>=4) Ptr[7-Index]='A'+(char)(LW&15);
  220.  return &Ptr[8];
  221. }
  222.  
  223. #define TAGIT(i,t,d) XpkTags[i].ti_Tag=t; XpkTags[i].ti_Data=(ULONG)d;
  224. #define ENDIT(i) XpkTags[i].ti_Tag=TAG_DONE;
  225.  
  226. LONG __regargs PackFile(struct DosLibrary *DOSBase,struct Library *XpkBase,
  227.                         char *SourceName,struct FileInfoBlock *FIB,char *Method,
  228.                         char *Suffix,LONG MinSize,char *Password,
  229.                         LONG Force,LONG Program,LONG xScan,LONG Lossy,LONG Quiet)
  230.  
  231. {
  232.  BPTR Handle;
  233.  struct TagItem XpkTags[10];
  234.  struct XpkFib XpkFib;
  235.  char ErrorBuffer[XPKERRMSGSIZE],TargetName[108];
  236.  LONG Error,Size;
  237.  
  238.  if (FIB->fib_Protection&FIBF_DELETE)
  239.   {
  240.    PrintF ("Skipping %s (delete protected)\n",SourceName);
  241.    return TRUE;
  242.   }
  243.  if (FIB->fib_Size<=MinSize)
  244.   {
  245.    PrintF ("Skipping %s (too small)\n",SourceName);
  246.    return TRUE;
  247.   }
  248.  if ((Handle=Open(FIB->fib_FileName,MODE_OLDFILE))==NULL)
  249.   {
  250.    PrintF ("Can't open %s\n",SourceName);
  251.    return TRUE;
  252.   }
  253.  if (!Force)
  254.   {
  255.    TAGIT(0,XPK_GetError,ErrorBuffer);
  256.    TAGIT(1,XPK_InFH,Handle);
  257.    ENDIT(2);
  258.    if (XpkExamine(&XpkFib,XpkTags))
  259.     {
  260.      Close (Handle);
  261.  
  262.      PrintF ("%s\n",ErrorBuffer);
  263.      return TRUE;
  264.     }
  265.    if (XpkFib.Type!=XPKTYPE_UNPACKED)
  266.     {
  267.      Close (Handle);
  268.  
  269.      PrintF ("Skipping %s (already crunched)\n",SourceName);
  270.      return TRUE;
  271.     }
  272.   }
  273.  if (Program)
  274.   {
  275.    LONG Buffer[5];
  276.  
  277.    if (Read(Handle,Buffer,20L)!=20L)
  278.     {
  279.      Close (Handle);
  280.  
  281.      PrintF ("Skipping %s (to small for executable)\n",SourceName);
  282.      return TRUE;
  283.     }
  284.    if (Buffer[0]!=0x3F3L)
  285.     {
  286.      Close (Handle);
  287.  
  288.      PrintF ("Skipping %s (not executable)\n",SourceName);
  289.      return TRUE;
  290.     }
  291.    if ((Buffer[3]!=0L)||((Buffer[4]+1L)!=Buffer[2]))
  292.     {
  293.      Close (Handle);
  294.  
  295.      PrintF ("Skipping %s (overlayed)\n",SourceName);
  296.      return TRUE;
  297.     }
  298.    (void)Seek(Handle,0L,OFFSET_BEGINNING);
  299.   }
  300.  
  301.  if (Suffix)
  302.   {
  303.    ULONG Length;
  304.  
  305.    Length=strlen(strcpy(TargetName,FIB->fib_FileName));
  306.    (void)strcpy(&TargetName[Length],Suffix);
  307.   }
  308.  else TempName (TargetName);
  309.  Size=0L;
  310.  
  311.  TAGIT(0,XPK_GetError,ErrorBuffer);
  312.  TAGIT(1,XPK_Password,Password);
  313.  TAGIT(2,XPK_FindMethod,Method);
  314.  TAGIT(3,XPK_ChunkHook,&ChunkHook);
  315.  if (Quiet) XpkTags[3].ti_Tag=TAG_IGNORE;
  316.  TAGIT(4,XPK_FileName,FIB->fib_FileName);
  317.  TAGIT(5,XPK_InFH,Handle);
  318.  TAGIT(6,XPK_OutName,TargetName);
  319.  TAGIT(7,XPK_GetOutLen,&Size);
  320.  TAGIT(8,XPK_LossyOK,Lossy);
  321.  if (!Lossy) XpkTags[8].ti_Tag=TAG_IGNORE;
  322.  ENDIT(9);
  323.  
  324.  if (Error=XpkPack(XpkTags))
  325.   {
  326.    Close (Handle);
  327.  
  328.    PrintF ("%s\n",ErrorBuffer);
  329.    return (Error!=XPKERR_ABORTED);
  330.   }
  331.  Close (Handle);
  332.  
  333.  if ((Size>FIB->fib_Size)&&(!Force))
  334.   {
  335.    (void)DeleteFile(TargetName);
  336.  
  337.    PrintF ("Skipping %s (unable to reduce size)\n",SourceName);
  338.    return TRUE;
  339.   }
  340.  
  341.  if (FIB->fib_Comment[0]=='\0')
  342.   if (xScan)
  343.    {
  344.     char *Ptr;
  345.  
  346.     Ptr=strcpy(FIB->fib_Comment,XFH_ID)+strlen(XFH_ID);
  347.     Ptr=ULTA(Ptr,FIB->fib_Date.ds_Days);
  348.     Ptr=ULTA(Ptr,FIB->fib_Date.ds_Minute);
  349.     Ptr=ULTA(Ptr,FIB->fib_Date.ds_Tick);
  350.     Ptr=ULTA(Ptr,Size);
  351.     *ULTA(Ptr,FIB->fib_Size)='\0';
  352.    }
  353.  
  354.  if (FIB->fib_Comment[0]) (void)SetComment(TargetName,FIB->fib_Comment);
  355.  
  356.  if (FIB->fib_Protection) (void)SetProtection(TargetName,FIB->fib_Protection);
  357.  (void)SetFileDate(TargetName,&FIB->fib_Date);
  358.  
  359.  if (Suffix) return TRUE;
  360.  
  361.  if (!DeleteFile(FIB->fib_FileName))
  362.   {
  363.    (void)DeleteFile(TargetName);
  364.  
  365.    PrintF ("Unable to delete %s\n",SourceName);
  366.    return TRUE;
  367.   }
  368.  if (!Rename(TargetName,FIB->fib_FileName))
  369.   {
  370.    PrintF ("Unable to rename %s to %s\n",TargetName,FIB->fib_FileName);
  371.    return FALSE;
  372.   }
  373.  
  374.  return TRUE;
  375. }
  376.  
  377. LONG __regargs UnPackFile(struct DosLibrary *DOSBase,struct Library *XpkBase,
  378.                           char *SourceName,char *Suffix,
  379.                           struct FileInfoBlock *FIB,char *Password,LONG Quiet)
  380.  
  381. {
  382.  BPTR Handle;
  383.  struct TagItem XpkTags[7];
  384.  struct XpkFib XpkFib;
  385.  char ErrorBuffer[XPKERRMSGSIZE],TargetName[108];
  386.  LONG SameFile,Error;
  387.  
  388.  if (FIB->fib_Protection&FIBF_DELETE)
  389.   {
  390.    PrintF ("Skipping %s (delete protected)\n",SourceName);
  391.    return TRUE;
  392.   }
  393.  if ((Handle=Open(FIB->fib_FileName,MODE_OLDFILE))==NULL)
  394.   {
  395.    PrintF ("Can't open %s\n",SourceName);
  396.    return TRUE;
  397.   }
  398.  
  399.  TAGIT(0,XPK_GetError,ErrorBuffer);
  400.  TAGIT(1,XPK_InFH,Handle);
  401.  ENDIT(2);
  402.  
  403.  if (XpkExamine(&XpkFib,XpkTags))
  404.   {
  405.    Close (Handle);
  406.  
  407.    PrintF ("%s\n",ErrorBuffer);
  408.    return TRUE;
  409.   }
  410.  if (XpkFib.Type!=XPKTYPE_PACKED)
  411.   {
  412.    Close (Handle);
  413.  
  414.    PrintF ("Skipping %s (not crunched)\n",SourceName);
  415.    return TRUE;
  416.   }
  417.  
  418.  TempName (TargetName);
  419.  SameFile=TRUE;
  420.  if (Suffix)
  421.   {
  422.    LONG Len1,Len2;
  423.  
  424.    Len1=strlen(FIB->fib_FileName);
  425.    Len2=strlen(Suffix);
  426.    if (Len1>Len2)
  427.     if (stricmp(&FIB->fib_FileName[Len1-Len2],Suffix)==0)
  428.      {
  429.       strcpy(TargetName,FIB->fib_FileName)[Len1-Len2]='\0';
  430.       SameFile=FALSE;
  431.      }
  432.   }
  433.  
  434.  TAGIT(0,XPK_GetError,ErrorBuffer);
  435.  TAGIT(1,XPK_Password,Password);
  436.  TAGIT(2,XPK_ChunkHook,&ChunkHook);
  437.  if (Quiet) XpkTags[2].ti_Tag=TAG_IGNORE;
  438.  TAGIT(3,XPK_FileName,FIB->fib_FileName);
  439.  TAGIT(4,XPK_InFH,Handle);
  440.  TAGIT(5,XPK_OutName,TargetName);
  441.  ENDIT(6);
  442.  
  443.  if (Error=XpkUnpack(XpkTags))   {
  444.    Close (Handle);
  445.  
  446.    PrintF ("%s\n",ErrorBuffer);
  447.    return (Error!=XPKERR_ABORTED);
  448.   }
  449.  Close (Handle);
  450.  
  451.  if (FIB->fib_Comment[0])
  452.   if (strncmp(FIB->fib_Comment,XFH_ID,strlen(XFH_ID))!=0)
  453.    (void)SetComment(TargetName,FIB->fib_Comment);
  454.  if (FIB->fib_Protection) (void)SetProtection(TargetName,FIB->fib_Protection);
  455.  (void)SetFileDate(TargetName,&FIB->fib_Date);
  456.  
  457.  if (!SameFile) return TRUE;
  458.  
  459.  if (!DeleteFile(FIB->fib_FileName))
  460.   {
  461.    (void)DeleteFile(TargetName);
  462.  
  463.    PrintF ("Unable to delete %s\n",SourceName);
  464.    return TRUE;
  465.   }
  466.  if (!Rename(TargetName,FIB->fib_FileName))
  467.   {
  468.    PrintF ("Unable to rename %s to %s\n",TargetName,FIB->fib_FileName);
  469.    return FALSE;
  470.   }
  471.  
  472.  return TRUE;
  473. }
  474.